package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.utils.ByteArray;
	
	import net.hires.debug.Stats;
	
	[SWF(width=500, height=500, frameRate=30)]
	public class CurvingRoad extends Sprite
	{
		public var bmp:Bitmap;
		public var bmd:BitmapData;
		public var mc:Sprite = new Sprite();
		
		public var road:ByteArray = new ByteArray();
		public var visibleRoad:Array = new Array();
		
		public var dir:Point = new Point();
		public var deltaDir:Point = new Point();
		public var altDir:Point = new Point();
		public var altDeltaDir:Point = new Point();
		public var matrix:Matrix = new Matrix();
		
		public var roadPiece1:Sprite;
		public var roadPiece2:Sprite;
		
		public const SEGMENT_LENGTH:int = 25;
		
		public function CurvingRoad()
		{
			addChild( new Stats() );
			
			this.roadPiece1 = drawRoadPiece(true);
			this.roadPiece2 = drawRoadPiece(false);
			
			bmd = new BitmapData(500,500,true,0x00000000);
			bmp = new Bitmap(bmd);
			this.addChild(bmp);
			
			var degrees:int = 0;
			var i:int
			var delta:int
			road.writeInt(degrees);
			
			i = 50;
			delta = 0;
			for( ; i>0; i--)
			{
				degrees += delta;
				road.writeInt(degrees);
			}
			for(var j:int=0; j<20; j++)
			{
				i = 60;
				delta = Math.random()*6-3;
				for( ; i>0; i--)
				{
					degrees += delta;
					road.writeInt(degrees);
				}
				degrees = degrees%360;
				if(degrees < 0) degrees = 360 + degrees;
			}
			i = degrees;
			delta = -1;
			for( ; i>0; i--)
			{
				degrees += delta;
				road.writeInt(degrees);
			}
			
			setupFullTrack();
			road.position=0;
			
			for(i=0; i<SEGMENT_LENGTH; i++)
			{
				visibleRoad[i] = road.readInt();
			}
			
			this.addEventListener(Event.ENTER_FRAME, onEnter);
		}
		
		protected function drawRoadPiece(bool:Boolean):Sprite
		{
			var sprite:Sprite = new Sprite();
			sprite.graphics.beginFill(0x303030,1);
			sprite.graphics.drawRect(-25,-10,50,20);
			sprite.graphics.endFill();
			if(bool)
			{
				sprite.graphics.lineStyle(3,0xFFFF00);
				sprite.graphics.moveTo(0,0);
				sprite.graphics.lineTo(0,5);
			}
			
			return sprite;
		}
		
		protected function setupFullTrack():void
		{
			mc.graphics.lineStyle(8);
			mc.x = 150;
			mc.y = 150;
			this.addChild(mc);
		}
		
		protected function onEnter(e:Event):void
		{
			if(road.position == road.length)
			{
				road.position = 0;
				mc.graphics.clear();
				mc.graphics.lineStyle(8);
				altDir.x = altDir.y = 0;
			}
			
			step();
			draw();
		}
		
		protected function step():void
		{
			var i:int = road.readInt();
			altDeltaDir.x = Math.sin(Math.PI*(i)/180);
			altDeltaDir.y = Math.cos(Math.PI*(i)/180);
			altDir.x += altDeltaDir.x;
			altDir.y += altDeltaDir.y;
			mc.graphics.lineTo(altDir.x, altDir.y);
			
			visibleRoad.shift();
			visibleRoad[SEGMENT_LENGTH-1] = i;
		}
		
		private var toggle:int = 0;
		protected function draw():void
		{
			dir.x = dir.y = 0;
			var first:int = visibleRoad[0];
			var next:int = 0;
			var i:int=1;
			
			toggle++;
			toggle = toggle&3;
			if(toggle == 0) toggle++;
			
			bmd.fillRect(bmd.rect, 0x00000000);
			for( ; i<SEGMENT_LENGTH; i++)
			{
				next = visibleRoad[i];
				deltaDir.x = Math.sin(Math.PI*(first-next)/180);
				deltaDir.y = Math.cos(Math.PI*(first-next)/180);
				dir.x += deltaDir.x*10;
				dir.y += deltaDir.y*10;
				
				matrix.a = deltaDir.y;
				matrix.b = deltaDir.x;
				matrix.c = -deltaDir.x;
				matrix.d = deltaDir.y;
				matrix.tx = 250+dir.x;
				matrix.ty = 500-dir.y;
				
				if((i+toggle)%3 == 0)
				{
					bmd.draw(this.roadPiece1, matrix);
				}
				else bmd.draw(this.roadPiece2, matrix);
			}
		}
	}
}